#include "StdAfx.h"
//-------------------------------------------------------------------------------------------------
//ImageProcessFile.h  - Declaration of an Image Processing File (IPF)         
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2012 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Feb 2012
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
#include "ImageProcessFile.h"
#include "ImageExptLib.h"


const char * const ImageProcessFile::Invalid = "Invalid";

const char * const ImageProcessFile::IpfRefPrefix = "IPFRef-";
const char * const ImageProcessFile::DateTimeFrmStr = "%d-%m-%y.%H:%M:%S";		//match with DateTimeFrmStrLen, ImageExpt::DateTimeFrmStr and ImageDataset::DateTimeFrmStrr

const char * const ImageProcessFile::xmlHeader = "IPF";
const char * const ImageProcessFile::xmlHeaderAttribName = "Name";
const char * const ImageProcessFile::xmlHeaderAttribDescription = "Description";
const char * const ImageProcessFile::xmlHeaderAttribStatus = "Status";
const char * const ImageProcessFile::xmlHeaderAttribIPFRef = "IPFRef";
const char * const ImageProcessFile::xmlHeaderAttribIEFRef = "IEFRef";
const char * const ImageProcessFile::xmlHeaderAttribOwner = "Owner";
const char * const ImageProcessFile::xmlHeaderAttribDate = "Created";

const char * const ImageProcessFile::xmlImages = "Images";									//match with ImageDataset::xmlImages
const char * const ImageProcessFile::xmlImage = "Image";									//match with ImageDataset::xmlImage
const char * const ImageProcessFile::xmlNoImageFilename = "[no image filename]";			//match with ImageDataset::xmlNoImageFilename

const char * const ImageProcessFile::StatusExperimental = "Experimental";		//must be less than ImageProcessFile::StatusLenMax 
const char * const ImageProcessFile::StatusProduction = "Production";			//must be less than ImageProcessFile::StatusLenMax 

ImageProcessFile::ImageProcessFile(void) : 
	_error(true),
	_ReadyToSetSteps(false),
	_pSteps('\0'),
	_pImageProcStepLibs('\0'),
	_PathFilename(""),
	_Name(ImageProcessFile::Invalid),
	_Description(ImageProcessFile::Invalid),
	_Status(ImageProcessFile::StatusExperimental),
	_IpfRef(ImageProcessFile::Invalid),
	_IefRef(ImageProcessFile::Invalid),
	_Owner(ImageProcessFile::Invalid),
	_Date(ImageProcessFile::Invalid)
{
	_buff[0] = '\0';
	_pSteps = new ImageProcSteps();
	_pImageProcStepLibs = new ImageProcStepLibs();
}

ImageProcessFile::~ImageProcessFile(void)
{
	if (_pSteps != '\0')
		delete _pSteps;
	_pSteps = '\0';
	if (_pImageProcStepLibs != '\0')
		delete _pImageProcStepLibs;
	_pImageProcStepLibs = '\0';
}

bool ImageProcessFile::Init (const wchar_t *intermedImagePathfilename, const wchar_t *imageProcLibDir)
{
	_ReadyToSetSteps = false;

	if ((intermedImagePathfilename == '\0') || (imageProcLibDir == '\0'))
		ImageExptLib::LogMsg("ImageProcessFile::ImageProcessFile::Init()", "Error: invalid input params");
	else
	{
		if ( (_pImageProcStepLibs == '\0') || (_pSteps == '\0' ) )
			ImageExptLib::LogMsg("ImageProcessFile::Init()", "Error: _pImageProcStepLibs is %s, _pSteps is %s", ((_pImageProcStepLibs == '\0') ? "null" : "not null"), ((_pSteps == '\0') ? "null" : "not null"));
		else
		{
			if (_pSteps->SetImageIntermediatePathFilename(intermedImagePathfilename) == false)
				ImageExptLib::LogMsg("ImageProcessFile::ImageProcessFile::Init()", "Error: _pSteps->SetImageIntermediatePathFilename() failed");
			else
			{
				if (InitLibs(imageProcLibDir) == false)
					ImageExptLib::LogMsg("ImageProcessFile::ImageProcessFile::Init()", "Error: _pSteps->SetImageIntermediatePathFilename() failed");
				else
					_ReadyToSetSteps = true;
			}
		}
	}
	return _ReadyToSetSteps;
}

bool ImageProcessFile::InitLibs (const wchar_t *imageProcLibDir)
{
	_ReadyToSetSteps = false;

	if (imageProcLibDir == '\0')
		ImageExptLib::LogMsg("ImageProcessFile::ImageProcessFile::InitLibs()", "Error: invalid input param");
	else
	{
		if ( (_pImageProcStepLibs == '\0') || (_pSteps == '\0' ) )
			ImageExptLib::LogMsg("ImageProcessFile::Init()", "Error: _pImageProcStepLibs is %s, _pSteps is %s", ((_pImageProcStepLibs == '\0') ? "null" : "not null"), ((_pSteps == '\0') ? "null" : "not null"));
		else
		{
			if (_pImageProcStepLibs->LoadLibs(imageProcLibDir) == false)
				ImageExptLib::LogMsg("ImageProcessFile::ImageProcessFile::Init()", "Error: _pSteps->SetImageIntermediatePathFilename() failed");
			else
				_ReadyToSetSteps = true;
		}
	}
	return _ReadyToSetSteps;
}

bool ImageProcessFile::Validate()
{
	_error = true;

	if ( (_pImageProcStepLibs == '\0') || (_pSteps == '\0' ) )
		ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error: _pImageProcStepLibs is %s, _pSteps is %s", ((_pImageProcStepLibs == '\0') ? "null" : "not null"), ((_pSteps == '\0') ? "null" : "not null"));
	else
	{
		if (_pSteps->IsValid() == false)
			ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error: _pSteps->IsValid() == false");
		else
		{
			if ( _Owner == ImageProcessFile::Invalid)
				ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error: _Owner == ImageProcessFile::Invalid");
			else
			{
				if ( _IefRef == ImageProcessFile::Invalid)
					ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error:  _IefRef == ImageProcessFile::Invalid");
				else
				{
					if (_Name == ImageProcessFile::Invalid)
						ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error:  _Name == ImageProcessFile::Invalid");
					else
					{
						if ( _Description == ImageProcessFile::Invalid)
							ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error:  _Description == ImageProcessFile::Invalid");
						else
						{
							if ((_IpfRef == ImageProcessFile::Invalid) || (_IpfRef.length() > ImageProcessFile::IEFRefLenMax))
								ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error:  _IpfRef == ImageProcessFile::Invalid or too long");
							else
							{
								if ( _Date == ImageProcessFile::Invalid)
									ImageExptLib::LogMsg("ImageProcessFile::Validate()", "Error:  _Date == ImageProcessFile::Invalid");
								else
									_error = false;
							}
						}
					}
				}
			}
		}
	}
	return IsValid();
}

bool ImageProcessFile::SetHeaderDetails(const wchar_t *name, const wchar_t *description, const wchar_t *status, const wchar_t *iefRef )
{
	_error = true;

	if ( (name == '\0') || (description == '\0') || (status == '\0') || (iefRef == '\0')  )
		ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "Error: invalid input params");
	else
	{
		if ( (_pSteps == '\0' ) || (_pSteps->IsValid() == false))
			ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "Error: invalid Steps");
		else
		{
			const char *p = '\0';
			if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), name, ImageProcessFile::NameLenMax)) == '\0')
				ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "name is too long");
			else
			{
				_Name = p;

				if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), description, ImageProcessFile::DescriptionLenMax)) == '\0')
					ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "description is too long");
				else
				{
					_Description = p;

					if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), status, ImageProcessFile::StatusLenMax )) == '\0')
						ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "status is too long");
					else
					{
						_Status = p;

						if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), iefRef, ImageProcessFile::IEFRefLenMax)) == '\0')
							ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "iefRef is too long");
						else
						{
							_IefRef = p;

							SetIdentity();

							if (Validate() == false)
								ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "Validate() failed");
						}
					}
				}
			}
		}
	}
	return IsValid();
}

bool ImageProcessFile::Save(const wchar_t *pathfilename)
{
	bool rc = false;

	if ( pathfilename == '\0') 
		ImageExptLib::LogMsg("ImageProcessFile::Save()", "Error: invalid input param");
	else
	{
		if (IsValid() == false)
			ImageExptLib::LogMsg("ImageProcessFile::Save()", "IsValid == false");
		else
		{
			const char *p = '\0';
			if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), pathfilename, ImageExptLib::MaxPathFileNameLen)) == '\0')
				ImageExptLib::LogMsg("ImageProcessFile::Save()", "pathfilename is too long");
			else
			{
				if ( SaveToXml(p) == false)
					ImageExptLib::LogMsg("ImageProcessFile::Save()", "SaveToXml() failed");
				else
					rc = true;
			}
		}
	}
	return rc;
}


bool ImageProcessFile::SaveToXml(const char *Pathfilename)
{
	bool rc = false;

	if ((Pathfilename == '\0') || (strlen (Pathfilename) < 1))
		ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "Pathfilename is null or invalid");
	else
	{
		_PathFilename = Pathfilename;
		if (IsValid() == false) 
			ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "IsValid == false");
		else
		{
			TiXmlDocument *pDoc = '\0';
			if ((pDoc = new TiXmlDocument(_PathFilename.c_str())) == '\0')
				ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to create document");
			else
			{
				TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "yes" );
				if ( pDoc->LinkEndChild( decl ) == '\0')
					ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to create TiXmlDeclaration");
				else
				{
					TiXmlComment * doctitle = new TiXmlComment( "Image workflow engine v0.0 - image process file" );
					if (pDoc->LinkEndChild( doctitle ) == '\0')
						ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to create TiXmlComment");
					else
					{
						TiXmlElement * content = new TiXmlElement( TinyXmlHelper::xmlDocName );
						if ( pDoc->LinkEndChild( content ) == '\0')
							ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to create TopNode");
						else
						{
							TiXmlElement * pHeader = new TiXmlElement( TinyXmlHelper::xmlHeaderElementName );
							if (content->LinkEndChild( pHeader ) == '\0')
								ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to create Header");
							else
							{
								if (SetHeader(pHeader) == false)
									ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to set Header");
								else
								{
									TiXmlElement * pBody = new TiXmlElement( TinyXmlHelper::xmlBodyElementName );
									if ( content->LinkEndChild( pBody ) == '\0')
										ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to create body");
									else
									{
										if (_pSteps->SaveSettingsToXml(pBody) == false)
											ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "SaveToIPF failed");
										else
										{
											if (pDoc->SaveFile() == false)
												ImageExptLib::LogMsg("ImageProcessFile::SaveToXml()", "failed to save xml");
											else
												rc = true;
										}
									}
								}
							}
						}
					}
				}
				delete pDoc;
			}
		}
	}
	return rc;
}

bool ImageProcessFile::SetHeader(TiXmlElement * pHeader)
{
	bool rc = false;

	if (pHeader == '\0')
		ImageExptLib::LogMsg("ImageProcessFile::SetHeader()", "invalid param");
	else
	{
		if (IsValid() == false)
			ImageExptLib::LogMsg("ImageProcessFile::SetHeader()", "IsValid() == false");
		else
		{
			TiXmlElement * ipf = new TiXmlElement( ImageProcessFile::xmlHeader );
			if ( pHeader->LinkEndChild( ipf) == '\0')
				ImageExptLib::LogMsg("ImageProcessFile::SetHeader()", "failed to save header");
			else
			{
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribName, _Name.c_str());
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribDescription, _Description.c_str());
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribStatus, _Status.c_str());
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribIPFRef, _IpfRef.c_str());
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribIEFRef, _IefRef.c_str());
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribOwner, _Owner.c_str());
				ipf->SetAttribute(ImageProcessFile::xmlHeaderAttribDate, _Date.c_str());

				rc = true;
			}
		}
	}
	return rc;
}

bool ImageProcessFile::SetPathFilename(const wchar_t *pathfilename)
{
	bool rc = false;

	if (pathfilename == '\0')
		ImageExptLib::LogMsg("ImageProcessFile::SetPathFilename()", "pathfilename is null");
	else
	{
		const char *p = '\0';
		if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), pathfilename, ImageExptLib::MaxPathFileNameLen )) == '\0')
			ImageExptLib::LogMsg("ImageProcessFile::SetHeaderDetails()", "pathfilename is too long");
		else
		{
			_PathFilename = p;
			rc = true;
		}
	}
	return rc;
}

bool ImageProcessFile::SetOwner(const wchar_t *owner)
{
	bool rc = false;

	if (owner == '\0')
		ImageExptLib::LogMsg("ImageProcessFile::SetOwner", "owner is null");
	else
	{
		const char *p = '\0';
		if ( (p = ImageExptLib::ConvertwStrToStr(_buff, (size_t)(sizeof(_buff)/sizeof(char)), owner, ImageProcessFile::OwnerLenMax )) == '\0')
			ImageExptLib::LogMsg("ImageProcessFile::SetOwner()", "owner name is too long");
		else
		{
			_Owner = p;
			rc = true;
		}
	}
	return rc;
}

void ImageProcessFile::SetIdentity()		
{
	SetDate();

	_IpfRef = ImageProcessFile::IpfRefPrefix;
	_IpfRef += _Owner;
	_IpfRef += "-";
	_IpfRef += _Date;
}

void ImageProcessFile::SetDate()
{
    char       buff[80]; 
    time_t t = time(0);   // get time now 
    struct tm * now = localtime( & t ); 
	strftime(buff, sizeof(buff), ImageProcessFile::DateTimeFrmStr, now); 
	_Date = buff;
}



//-------------------------------------------------------------------------------------------------
//			E N D   O F   F I L E
//-------------------------------------------------------------------------------------------------